<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2020/12/10
 * Time: 16:42
 */
namespace app\common\widget\weixin;

use app\common\config\weixin_config;
use app\common\helper\appmenu_helper;
use app\common\helper\company_helper;
use app\common\helper\emotion_helper;
use app\common\helper\open_card_helper;
use app\common\helper\setting_helper;
use app\common\helper\user_helper;
use app\common\helper\weixin_helper;
use app\common\model\Appmedia;

class weixin_widget
{
    private $company_id;
    private $open_card_id;
    private $appmenu_key = array();
    private $appid;
    private $appsecret;
    private $access_token;

    public function __construct()
    {
        $this->open_card_id   = open_card_helper::get_open_card_id();
        $this->company_id     = company_helper::get_company_id();

        $appmenu_key = setting_helper::get_setting_info('appmenu_key');
        if ($appmenu_key) {
            $this->appmenu_key = unserialize($appmenu_key);

            $this->appid        = $this->appmenu_key['appid'];
            $this->appsecret    = $this->appmenu_key['appsecret'];
            $this->access_token = $this->appmenu_key['access_token'];
        }
        //var_dump($this->open_card_id,$this->company_id,$appmenu_key,222);
    }

    /**
     * 发送客服信息
     * @param unknown $params
     * @return string
     */
    public function send($params)
    {
        if (!$this->appmenu_key) {
            return '未设置appid,appsecret等相关信息';
        }

        if (!$params) {
            return '发送参数不能为空';
        }

        $user_id  = isset($params['user_id']) ? $params['user_id'] : 0;
        $open_id  = isset($params['open_id']) ? $params['open_id'] : 0;
        $type     = isset($params['type']) ? $params['type'] : '';
        $media_id = isset($params['media_id']) ? $params['media_id'] : '';
        $content  = isset($params['content']) ? $params['content'] : '';
        $msg_arr  = isset($params['msg_arr']) ? $params['msg_arr'] : '';

        if (!$user_id && !$open_id) {
            return '请传递要发送的目标人';
        }
        if (!$open_id) {
            $open_id = user_helper::get_open_id($user_id);
        }
        if (!$open_id) {
            return '请传递要发送的目标人';
        }

        if (!$type) {
            return '请传递要发送的消息类型';
        }

        if ($type == 'text') {
            if (!$content) {
                return '内容不能为空';
            }

        } else if ($type == 'news') {
            if (!$msg_arr) {
                return '图文不能为空';
            }

        } else {
            if (!$media_id) {
                return '媒体文件的media_id不能为空';
            }
        }
        //an_dump('qianm');

        //@todo 可以转移到__construct
        if (!$this->access_token) {
            $check_flag = $this->check_app_params();
            if ($check_flag) {
                return $check_flag;
            }
        }

        $send_url = str_replace('{ACCESS_TOKEN}', $this->access_token, weixin_config::$service_send_url);

        if ('text' == $type) {
            $data = $this->build_text($user_id, $open_id, $content);

        } else if ('news' == $type) {
            $data = $this->build_news($user_id, $open_id, $msg_arr);

        } else if ('image' == $type) {
            $data = $this->build_image($open_id, $media_id);

        } else if ('voice' == $type) {
            $data = $this->build_voice($open_id, $media_id);

        } else if ('video' == $type) {
            $data = $this->build_video($open_id, $media_id);

        } else if ('mpnews' == $type) {
            $data = $this->build_mpnews($open_id, $media_id);
        }
        //an_dump($send_url, $data, 1);
        //exit;

        $res = curl($send_url, "POST", $data);
        //an_dump($res, '01');exit;
        if (isset($res->errmsg) && $res->errmsg != 'ok') {
            if ($user_id == 100128) {
                //an_dump($res, '01');
            }

            // 如果accesss_token失效，重新发送一次
            if ($res->errcode == '42001' || $res->errcode == '40001') {
                $check_flag = $this->check_app_params();
                if ($check_flag) {
                    return $check_flag;
                }

                $send_url = str_replace('{ACCESS_TOKEN}', $this->access_token, weixin_config::$service_send_url);

                $res = curl($send_url, "POST", $data);
            }
        }

        if ($user_id == 100128) {
            //an_dump($res);
            //exit;
        }

        if (isset($res->errmsg) && $res->errmsg != 'ok') {
            //an_dump($res);
            if (array_key_exists($res->errcode, weixin_config::$err_code)) {
                return weixin_config::$err_code[$res->errcode];
            }

            return '回复失败'.$res->errcode;
        }

        return 'ok';
    }

    /**
     * 取粉丝的信息
     * @param array $params
     * @return multitype:|string
     */
    public function get_wx_user_info($params)
    {
        $user_id = isset($params['user_id']) ? $params['user_id'] : 0;
        $open_id = isset($params['open_id']) ? $params['open_id'] : 0;
        if (!$user_id && !$open_id) {
            return array();
        }
        if (!$open_id) {
            $open_id = user_helper::get_open_id($user_id);
        }
        if (!$open_id) {
            return array();
        }
        //var_dump($this->access_token, 111);
        $url = str_replace('{ACCESS_TOKEN}', $this->access_token, weixin_config::$get_user_url);
        $url = str_replace('{OPENID}', $open_id, $url);
        $res = h_curl($url, null, 1);
        if (isset($res['errmsg']) && $res['errmsg'] != 'ok') {
            // 如果accesss_token失效，重新一次
            if (in_array($res['errcode'], array('42001', '40001', '41001'))) {
                $check_flag = $this->check_app_params();
                if ($check_flag) {
                    return $check_flag;
                }

                $url = str_replace('{ACCESS_TOKEN}', $this->access_token, weixin_config::$get_user_url);
                $url = str_replace('{OPENID}', $open_id, $url);

                $res = h_curl($url, null, 1);
            }
        }

        if (isset($res->errmsg) && $res->errmsg != 'ok') {
            //an_dump($res);
            if (array_key_exists($res['errcode'], weixin_config::$err_code)) {
                return weixin_config::$err_code[$res['errcode']];
            }

            return '取信息失败'.$res['errcode'];
        }

        return $res;
        /*
         *返回数据示例
         *
{
   "subscribe": 1,
   "openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M",
   "nickname": "Band",
   "sex": 1,
   "language": "zh_CN",
   "city": "广州",
   "province": "广东",
   "country": "中国",
   "headimgurl":  "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4
eMsv84eavHiaiceqxibJxCfHe/0",
  "subscribe_time": 1382694957,
  "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"
  "remark": "",
  "groupid": 0,
  "tagid_list":[128,2]
}
         */
    }

    /**
     * 取所有粉丝的openid
     * @param array $params
     * @return multitype:|string
     */
    public function get_wx_user_open_id($next_openid = '')
    {

        $url = str_replace('{ACCESS_TOKEN}', $this->access_token, weixin_config::$get_user_open_id_url);
        if ($next_openid) {
            $url = $url.'&next_openid='.$next_openid;
        }

        $res = h_curl($url, null, 1);
        if (isset($res['errmsg']) && $res['errmsg'] != 'ok') {
            // 如果accesss_token失效，重新一次
            if (in_array($res['errcode'], array('42001', '40001', '41001'))) {
                $check_flag = $this->check_app_params();
                if ($check_flag) {
                    return $check_flag;
                }

                $res = h_curl($url, null, 1);
            }
        }

        if (isset($res->errmsg) && $res->errmsg != 'ok') {
            //an_dump($res);
            if (array_key_exists($res['errcode'], weixin_config::$err_code)) {
                return weixin_config::$err_code[$res['errcode']];
            }

            return '取信息失败'.$res['errcode'];
        }

        return $res;

    }

    /**
     * 下载多媒体
     * @param  array $params
     * @return string
     */
    public function download($params, $type = 'voice')
    {
        $media_id       = isset($params['media_id']) ? $params['media_id'] : '';
        //$file_path  = isset($params['file_path']) ? $params['file_path'] : '';

        if (!$media_id) {
            return '多媒体media_id不能为空';
        }

        if (!$this->access_token) {
            $check_flag = $this->check_app_params();
            if ($check_flag) {
                return $check_flag;
            }
        }

        $upload_url = str_replace(array('{ACCESS_TOKEN}', '{MEDIA_ID}'), array($this->access_token, $media_id), weixin_config::$download_url);
        $res = $this->download_weixin_file($upload_url);

        if (isset($res->errmsg) && $res->errmsg != 'ok') {
            // 如果accesss_token失效，重新发送一次
            if ($res->errcode == '42001' || $res->errcode == '40001') {
                $check_flag = $this->check_app_params();
                if ($check_flag) {
                    return $check_flag;
                }

                $upload_url = str_replace(array('{ACCESS_TOKEN}', '{MEDIA_ID}'), array($this->access_token, $media_id), weixin_config::$download_url);

                $res = $this->download_weixin_file($upload_url);
            }
        }

        if (isset($res->errmsg) && $res->errmsg != 'ok') {
            dump($res);
            if (array_key_exists($res->errcode, weixin_config::$err_code)) {
                return weixin_config::$err_code[$res->errcode];
            }

            return '下载失败';
        }

        //an_dump($res);exit;
        // 取得media_id后的处理
        $file_type = 'amr';
        $file_name = build_target_name($file_type);
        $this->save_weixin_file($file_name, $res['body']);

        $file_path = str_replace(UPLOAD_PATH, '', $file_name);
        // 下载的文件入库
        $new_media_info = array(
            'company_id'   => $this->company_id,
            'open_card_id' => $this->open_card_id,
            'path'         => $file_path,
            'media_id'     => $media_id,
            'expires_time' => date('Y-m-d H:i:s'),
            'come_from'    => 2
        );
        if ($type == 'voice') {
            $new_media_info['type'] = 20;
        } else if ($type == 'video') {
            $new_media_info['type'] = 30;
        } else {
            $new_media_info['type'] = 10;
        }

        Appmedia::create($new_media_info);
        return $file_path;
    }

    // 下载多媒体
    private function download_weixin_file($url)
    {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_NOBODY, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $package = curl_exec($ch);
        $httpinfo = curl_getinfo($ch);
        curl_close($ch);

        $res = json_decode($package);
        if (isset($res->errmsg) && $res->errmsg) {
            return $res;
        }

        $info = array_merge(array('header' => $httpinfo), array('body' => $package));

        return $info;
    }

    // 保存下载的多媒体
    private function save_weixin_file($filename, $filecontent)
    {
        $local_file = fopen($filename, 'w');
        if (false !== $local_file){
            if (false !== fwrite($local_file, $filecontent)) {
                fclose($local_file);
            }
        }

        return true;
    }

    /**
     * 获取带参二维码的ticket
     */
    public function get_qrode_ticket($scene_id, $type = 2)
    {
        $get_ticket_url = str_replace('{ACCESS_TOKEN}', $this->access_token, weixin_config::$qrode_ticket_url);
        if (2 == $type) {
            if (is_numeric($scene_id)) {
                $post_data = '{"action_name": "QR_LIMIT_SCENE", "action_info": {"scene": {"scene_id": '.$scene_id.'}}}';
            } else {
                $post_data = '{"action_name": "QR_LIMIT_STR_SCENE", "action_info": {"scene": {"scene_str": "'.$scene_id.'"}}}';
            }
        } else {
            $post_data = '{"expire_seconds": 2591000, "action_name": "QR_SCENE", "action_info": {"scene": {"scene_id": '.$scene_id.'}}}';
        }

        $res = h_curl($get_ticket_url, $post_data, true);
        if (isset($res['errmsg'])) {

            // 如果accesss_token失效，重新发送一次
            if ($res['errcode'] == '42001' || $res['errcode'] == '40001') {
                $check_flag = $this->check_app_params();
                if ($check_flag) {
                    return $check_flag;
                }

                $get_ticket_url = str_replace('{ACCESS_TOKEN}', $this->access_token, weixin_config::$qrode_ticket_url);

                $res = h_curl($get_ticket_url, $post_data, true);
            }
        }

        if (isset($res['errmsg'])) {
            if (array_key_exists($res['errcode'], weixin_config::$err_code)) {
                return weixin_config::$err_code[$res['errcode']];
            }

            return '失败';
        }
        //an_dump($res);exit;

        return $res;
    }

    /**
     * 检查并更新appid appsecret accesstoken
     * @return string
     */
    private function check_app_params()
    {
        $access_token = appmenu_helper::get_access_token_new($this->appid, $this->appsecret);
        if (!$access_token) {
            return '获取凭证失败，请检查授权信息';
        }

        $this->appmenu_key['access_token'] = $access_token;
        $this->appmenu_key['expire_time']  = time()+7200;
        $this->access_token = $access_token;
        setting_helper::update_setting_info('appmenu_key', serialize($this->appmenu_key));

        return '';
    }

    /**
     * 上传多媒体
     * @param  array $params
     * @return string
     */
    public function upload($params)
    {
        $type       = isset($params['type']) ? $params['type'] : '';
        $file_path  = isset($params['file_path']) ? $params['file_path'] : '';

        if (!$type) {
            return '多媒体类型不能为空';
        }
        if (!$file_path) {
            return '多媒体文件不能为空';
        }
        if (strpos($file_path, UPLOAD_PATH) === false) {
            $file_path = UPLOAD_PATH.'/'.ltrim($file_path, '/');
        }

        if (!$this->access_token) {
            $check_flag = $this->check_app_params();
            if ($check_flag) {
                return $check_flag;
            }
        }

        //var_dump($file_path, $type);exit;
        //$data = array("media"  => "@".$file_path);
        $tmp_image_info = getimagesize($file_path);
        $tmp_image_type = '';
        if (isset($tmp_image_info['mime'])) {
            $tmp_image_type = $tmp_image_info['mime'];
        }
        $tmp_image_name = basename($file_path);
        $data = array("media"  => new \CURLFile($file_path, $tmp_image_type, $tmp_image_name));
        //var_dump($file_path, $data);
        $upload_url = str_replace(array('{ACCESS_TOKEN}', '{TYPE}'), array($this->access_token, $type), weixin_config::$upload_url);

        $res = h_curl($upload_url, $data, 1);

        //an_dump($res, '01');
        if (isset($res['errcode']) && $res['errcode'] != 0) {
            //an_dump($res, isset($res->errmsg), 1);
            // 如果accesss_token失效，重新发送一次
            if ($res['errcode'] == '42001' || $res['errcode'] == '40001') {
                $check_flag = $this->check_app_params();
                if ($check_flag) {
                    return $check_flag;
                }

                $upload_url = str_replace(array('{ACCESS_TOKEN}', '{TYPE}'), array($this->access_token, $type), weixin_config::$upload_url);

                $res = h_curl($upload_url, $data, 1);
            }
        }

        if (isset($res['errcode']) && $res['errcode'] != 0) {

            //an_dump($res, 2);
            if (array_key_exists($res['errcode'], weixin_config::$err_code)) {
                return weixin_config::$err_code[$res['errcode']].' '.$res['errcode'].' '.$file_path;
            }

            return '上传文件失败'.$res['errcode'];
        }

        //an_dump($res, 2001);
        //exit;
        return $res;
        // 上传后的处理
    }

    /**
     * 校正链接后的参数
     */
    private function fix_link($str, $user_id)
    {
        if (strpos($str, 'wx_id=wx_id') !== false) {
            //$str = str_replace('wx_id=wx_id', 'wx_id='.$user_id, $str);
        }

        //$reg = '/(http[^\x{4e00}-\x{9fa5}\s]+)/u';
        $reg = '/[^"](http[a-zA-Z0-9=_\?\&\.\-\:\/]+)/u';
        $flag = preg_match_all($reg, $str, $matches);
        if ($flag && isset($matches[1]) && $matches[1]) {
            $unique_arr = array_unique($matches[1]);
            foreach($unique_arr as $k=>$v) {
                if (strpos($v['link'], '?') === false) {
                    $tmp_link = $v.'?wx_id='.$user_id;
                } else {
                    $tmp_link = $v.'&wx_id='.$user_id;
                }
                $str = str_replace($v, '<a href=\''.$tmp_link.'\'>'.$v.'</a>', $str);
            }
        }

        return $str;
    }

    /**
     * 文本内容的一些处理
     */
    private function fix_real_content($content, $user_id)
    {
        $content = $this->fix_link($content, $user_id);

        $content = html_entity_decode($content);
        //$content = str_replace('<br>', "\n", $content);
        $content = preg_replace('/\<br.*?\>/', "\n", $content);
        $content = strip_tags($content, '<a><img>');
        $content = str_replace('&nbsp;', '', $content);

        $content = emotion_helper::image_to_str($content);

        return $content;
    }

    /**
     * 组装文本回复
     * @param string $open_id
     * @param string $content
     * @return string
     */
    public function build_text($user_id, $open_id, $content)
    {
        $content = $this->fix_real_content($content, $user_id);

        $data = '{
                    "touser":"'.$open_id.'",
                    "msgtype":"text",
                    "text":
                    {
                         "content":"'.$content.'"
                    }
                }';
        /*$data_arr = array(
            'touser'  => ''.$open_id,
            'msgtype' => 'text',
            'text'    => array(
                'content' => ''.$content
            )
        );
        $data = json_encode($data_arr);*/

        return $data;
    }

    /**
     * 组将图文信息
     * @param int $user_id
     * @param string $open_id
     * @param array $msg_arr
     * @return string
     */
    public function build_news($user_id, $open_id, $msg_arr)
    {
        $data = '{
                    "touser":"'.$open_id.'",
                    "msgtype":"news",
                    "news":{
                        "articles": [';

        foreach ($msg_arr as $k=>$v) {
            if (strpos($v['cover'], 'http:/') === false) {
                //@todo 第一条取大图
                if ($k == 0) {
                    $v['cover'] = _image($v['cover'], 'big');

                    // 后面的条数取小图
                } else {
                    $v['cover'] = _image($v['cover'], 'big');
                }
                if (strpos($v['cover'], SITE_URL) === false) {
                    $v['cover'] = SITE_URL.$v['cover'];
                }
            }

            //@todo 如果没有指定特殊的跳转地址，则指向该信息详情页
            if (!isset($v['link']) || !$v['link']) {
                $v['link'] = SITE_URL.'/appmsg/m/'.$v['id'];
            }
            if (strpos($v['link'], '?') === false) {
                //$v['link'] .= '?wx_id='.$user_id;
            } else {
                //$v['link'] .= '&wx_id='.$user_id;
            }

            $data .= '{
                 "title":"'.$v['title'].'",
                 "description":"'.$v['intro'].'",
                 "url":"'.$v['link'].'",
                 "picurl":"'.$v['cover'].'"
             }';
            if (isset($msg_arr[$k+1]) && $msg_arr[$k+1]) {
                $data .= ',';
            }
        }

        $data .= ']
                }
            }';

        return $data;
    }

    /**
     * 组装微信公众号上永久图文的发送信息
     * @param string $open_id
     * @param string $media_id
     * @return string
     */
    public function build_mpnews($open_id, $media_id)
    {
        $data = '{
                    "touser":"'.$open_id.'",
                    "msgtype":"mpnews",
                    "mpnews":
                    {
                         "media_id":"'.$media_id.'"
                    }
                }';

        return $data;
    }

    /**
     * 组装图片信息
     * @param string $open_id
     * @param string $media_id
     * @return string
     */
    public function build_image($open_id, $media_id)
    {
        $data = '{
                    "touser":"'.$open_id.'",
                    "msgtype":"image",
                    "image":
                    {
                         "media_id":"'.$media_id.'"
                    }
                }';

        return $data;
    }

    /**
     * 组装声音信息
     * @param string $open_id
     * @param string $media_id
     * @return string
     */
    public function build_voice($open_id, $media_id)
    {
        $data = '{
                    "touser":"'.$open_id.'",
                    "msgtype":"voice",
                    "voice":
                    {
                         "media_id":"'.$media_id.'"
                    }
                }';

        return $data;
    }

    /**
     * 组装视频信息
     * @param string $open_id
     * @param string $media_id
     * @param string $title
     * @param string $description
     * @return string
     */
    public function build_video($open_id, $media_id, $title = '', $description = '')
    {
        $data = '{
                    "touser":"'.$open_id.'",
                    "msgtype":"video",
                    "video":
                    {
                        "media_id":"'.$media_id.'",
                        "title":"'.$title.'",
                        "description":"'.$description.'"
                    }
                }';

        return $data;
    }

    /**
     * 预览微信公众号的上的素材（图片、视频、图文等）
     * @param  string $media_id 素材id（公众上的素材）
     * @param  string $open_id  用户openid
     * @return
     */
    public function preview($media_id, $open_id)
    {
        if (!$open_id) {
            return '未知的用户';
        }

        if (!$this->access_token) {
            $check_flag = $this->check_app_params();
            if ($check_flag) {
                return $check_flag;
            }
        }

        $send_url = str_replace('{ACCESS_TOKEN}', $this->access_token, weixin_config::$preview_url);
        $data     = $this->build_mpnews($open_id, $media_id);
        $res      = h_curl($send_url, $data, 1);
        if (isset($res['errcode']) && $res['errcode'] != 0) {
            // 如果accesss_token失效，重新发送一次
            if ($res['errcode'] == '42001' || $res['errcode'] == '40001') {
                $check_flag = $this->check_app_params();
                if ($check_flag) {
                    return $check_flag;
                }

                $send_url = str_replace('{ACCESS_TOKEN}', $this->access_token, weixin_config::$service_send_url);

                $res = h_curl($send_url, $data, 1);
            }
        }

        //dump($res);exit;
        if (isset($res['errcode']) && $res['errcode'] != 0) {
            // 计入log
            //$log_content = 'Open_id:'.$open_id.'~~~ERR:'.$res->errcode.'';
            //write_log_helper::write_log('send_msg_error', $log_content, 'msg_error_code');

            if (array_key_exists($res['errcode'], weixin_config::$err_code)) {
                return weixin_config::$err_code[$res['errcode']];
            }

            return '发送预览失败'.$res['errcode'].' '.$res['errmsg'];
        }

        return 'ok';
    }

    /**
     * api调用次数进行清零
     * @return
     */
    public function clear_quota()
    {
        if (!$this->access_token) {
            $check_flag = $this->check_app_params();
            if ($check_flag) {
                return $check_flag;
            }
        }

        $api_log_info = array(
            'file'      => substr(__FILE__, strrpos(__FILE__, '/')+1),
            'action'    => __FUNCTION__
        );
        weixin_helper::add_api_log($api_log_info);
        //an_dump(__FILE__, __FUNCTION__, __METHOD__, strrpos(__FILE__, '/'), strpos(__FILE__, '/'), );
        //exit;

        $send_url = str_replace('{ACCESS_TOKEN}', $this->access_token, weixin_config::$clear_quota_url);
        $data     = array('appid'=>$this->appid);
        $data     = json_encode($data);
        $res      = h_curl($send_url, $data, 1);
        if (isset($res['errcode']) && $res['errcode'] != 0) {
            // 如果accesss_token失效，重新发送一次
            if ($res['errcode'] == '42001' || $res['errcode'] == '40001') {
                $check_flag = $this->check_app_params();
                if ($check_flag) {
                    return $check_flag;
                }

                $send_url = str_replace('{ACCESS_TOKEN}', $this->access_token, weixin_config::$clear_quota_url);

                $res = h_curl($send_url, $data, 1);
            }
        }

        //an_dump($res);//exit;
        if (isset($res['errcode']) && $res['errcode'] != 0) {
            if (array_key_exists($res['errcode'], weixin_config::$err_code)) {
                return weixin_config::$err_code[$res['errcode']];
            }

            return '清除次数失败 '.$res['errcode'].' '.$res['errmsg'];
        }

        return 'ok';
    }
}